HomeArchiveFeedShelf

Deploy Perforce Server into Kubernetes

Why Perforce

Perforce is a version control tool just like git, svn, but optimized for large binary files.

Perforce is widely used by top tier game studios like Naughty Dogs, Electronic Arts and Ubisoft.

To me, the reason I choose Perfoce rather than Git LFS is that I already have a k8s cluster up and running and don't want to buy datapacks on Github as there would be large, large asset files for game projects.

Dockerfile

All my nodes are arm64-based AWS virtual machines. Perforce don't maintain Linux packages for arm64 anymore. I tried the way to build docker image by downloading binaries and it worked.

FROM ubuntu:jammy

# Update our main system
RUN apt-get update -y

# Install dependencies
RUN apt-get install -y wget tar

# Set the working directory
WORKDIR /perforce

# Download and extract Perforce binaries
RUN wget https://www.perforce.com/downloads/perforce/r24.1/bin.linux26aarch64/helix-core-server.tgz -O helix-core-server.tgz \
    && tar -xzf helix-core-server.tgz \
    && rm helix-core-server.tgz

# Add Perforce binaries to PATH
ENV PATH="/perforce:${PATH}"

# Define environment variables for Perforce
ENV P4ROOT=/perforce
ENV P4PORT=1666

# Expose the Perforce server port
EXPOSE 1666

# Start Perforce server and tail logs
CMD p4d -r /perforce -p $P4PORT -L /perforce/logs/log && tail -F /perforce/logs/log

The download url can be found on official perforce download page. By the time when this article is written, the latest version for helix server is 2024.1/2596294. Be sure to check new releases when you make your own docker image.

Build and push to registry

#!/bin/bash

# Variables
repositoryHost='your-registry'
repository='your-repo'
imageBaseName='helix-core-server'
platforms='linux/arm64' # Define platforms

# Extract version from package.json
version='0.0.1'

# Full image tag with version
imageTag="$imageBaseName:$version"

# Create a new builder instance that supports multi-platform builds, if not already done
docker buildx create --name mymultiarchbuilder --use

# Start up the build instance, if not already done
docker buildx inspect --bootstrap

# Build and push Docker image
docker buildx build --platform $platforms -t $repositoryHost/$repository/$imageTag --push .

K8s Deployment

Everytime I expose a service from my k8s cluster I will consider DDoS problem because you will meet them sooner or later if you don't. Usually I expose them through nodeport + nginx ingress controller, and put them behind cloudflare.

However Perforce is not a http service and cannot be proxied through cloudflare orange cloud. I have to disable orange cloud and access them directly using nodeport. It is not a big problem because I only use it for myself. If the Perforce server is going to be public over the Internet, you will have to consider DDoS protection.

deployment.yaml

I already have a PVC setup based on juicefs in my k8s cluster, so the pod will not lose any data during redeployments. I mapped data/perforce-root in juicefs for /etc/perforce and /perforce inside container. Make sure to adjust it for your case.

This article doesn't talk about how to deploy juicefs to your k8s cluster as PersistentVolume. They are detailed written in the official documentation of juicefs.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: perforce-server
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: perforce-server
  template:
    metadata:
      labels:
        app: perforce-server
    spec:
      containers:
        - name: perforce-server
          image: your-registry/helix-core-server:0.0.1
          ports:
            - containerPort: 1666
          volumeMounts:
            - mountPath: /etc/perforce
              name: perforce-storage
              subPath: data/perforce-root/etc/perfoce
            - mountPath: /perfoce
              name: perforce-storage
              subPath: data/perfoce-root/perfoce
          env:
            - name: P4ROOT
              value: /perforce
            - name: P4PORT
              value: "1666"
      volumes:
        - name: perforce-storage
          persistentVolumeClaim:
            claimName: juicefs-pvc

nodeport.yaml

apiVersion: v1
kind: Service
metadata:
  name: perforce-service
  namespace: default
spec:
  type: NodePort
  ports:
    - port: 1666
      targetPort: 1666
  selector:
    app: perforce-server

Apply them

kubectl apply -f deployment.yaml
kubectl apply -f nodeport.yaml

Check port k8s assigned for perforce-server by

kubectl get svc

In my case the port is 30222. Point your domain to the public IP of node. Your Perforce address is your-domain:30222. Remember to adjust your firewall or other related security policies.

Set Password

Although you can do this step using init containers with some tricks and let k8s do this for you, it is tedious so I just get into the pod and do it manually and only once because the setup will be persistent as the pod is provided with PVC.

Get pod name

kubectl get pods -l app=perforce-server

Then get into it

kubectl exec -it pod-name-you-just-got -it -- /bin/bash

Enable authorization

p4 protect -o > protections.p4s

In googled results, the usernames of admin are supers but in my protection.p4s I only see a root. Never mind, just set password for root

p4 -u root passwd

Now you can connect to Perforce server using your-domain:30222 with root and password.

You can connect to it with root using p4admin GUI client and create users with normal permission for daily development.

Reference

@2024-05-18 16:20